package com.chat.transmission.service.impl;

import cn.hutool.json.JSONUtil;
import com.chat.common.common.constant.RedisKeyConstant;
import com.chat.common.vo.GroupVO;
import com.chat.common.vo.R;
import com.chat.openfeign.client.BusinessDataService;
import com.chat.transmission.service.BusinessService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author wei kunJie
 * @date 2024/4/26 18:43:07
 */
@Service
@Slf4j
public class BusinessServiceImpl implements BusinessService {

    @Resource
    private RedisTemplate<String, String> redisTemplate;
    @Resource
    private BusinessDataService businessDataService;
    @Resource
    private RedissonClient redissonClient;

    /**
     * 用户获取群信息
     *
     * @param userId
     * @return
     */
    @Override
    public List<GroupVO> getUserGroups(Long userId) {
        //加锁避免用户多次查询击穿缓存
        //获取一把锁，只要锁的名字一样，就是同一把锁
        RLock lock = redissonClient.getLock("Lock:" + RedisKeyConstant.USER_GROUP_CACHE + userId);
        lock.lock(5, TimeUnit.SECONDS);//加锁，阻塞式等待 5s，默认加的锁都是30s
        //先去Redis中查缓存
        String json = redisTemplate.opsForValue().get(RedisKeyConstant.USER_GROUP_CACHE + userId);
        List<GroupVO> groupVOS;
        if (json == null) {
//            log.info("查询用户id={}有哪些群，无缓存",userId);
            //没有再远程调用查数据库
            R<List<GroupVO>> r = businessDataService.getUserGroups(userId);
            if (r.getCode() == 200) {
                groupVOS = r.getData();
                if (groupVOS == null) groupVOS = new ArrayList<>();
                //redis缓存
                redisTemplate.opsForValue().set(RedisKeyConstant.USER_GROUP_CACHE + userId, JSONUtil.toJsonStr(groupVOS));
//                log.info("查询用户id={}有哪些群，无缓存，查询数据库得到：{}，并更新缓存完成",userId,JSONUtil.toJsonStr(groupVOS));
                lock.unlock();//缓存完成，释放锁
            } else {
                lock.unlock();//释放锁
//                log.error("查询用户有哪些群，远程调用失败 code:{},msg={}", r.getCode(), r.getMsg());
                return null;
            }
        } else {
//            log.info("查询用户id={}有哪些群，有缓存",userId);
            lock.unlock();//缓存中有，直接释放锁
            groupVOS = JSONUtil.toList(json, GroupVO.class);
        }
        return groupVOS;

    }

    /**
     * 更新用户获取群信息
     * @param groupVOList
     * @param userId
     */
    @Override
    public void updateUserGroupsCache(List<GroupVO> groupVOList,Long userId) {
        //加锁避免用户多次查询击穿缓存
        //获取一把锁，只要锁的名字一样，就是同一把锁
        RLock lock = redissonClient.getLock("Lock:" + RedisKeyConstant.USER_GROUP_CACHE + userId);
        lock.lock(5, TimeUnit.SECONDS);//加锁，阻塞式等待 5s，默认加的锁都是30s
        //更新redis缓存
        redisTemplate.opsForValue().set(RedisKeyConstant.USER_GROUP_CACHE + userId, JSONUtil.toJsonStr(groupVOList));
        lock.unlock();//更新完成，释放锁
    }


}
